
                /*********************************************
                **                                          **
                **                                          **
                **                g.l.i.nb.C                **
                **                                          **
                **                                          **
                *********************************************/
                /*********************************************
                **                                          **
                **         Author Jean-Marc Adamo           **
                **           Copyright (C) 1997 JMA         **
                *********************************************/

/*
** Indirect Access Global and Non-Blocking Global Read/Write Function 
** Needs 3 processors
*/


#include "arch.h"

Global_id gid;
Coll_id cid1, cid2, cid3, cid4;

void init_gid(int, char **){
   gid.set();
   cid1.set();
   cid2.set();
   cid3.set();
   cid4.set();
   fprintf(Sdf::trace, "from node %d: gid=%d, cid1=%d, cid2=%d, cid3=%d, cid4=%d\n", 
           Sdf::PROC_ID, gid.get(), cid1.get(), cid2.get(), cid3.get(), cid4.get());
   fflush(Sdf::trace);
}

char *rw_target_adrs;

int count;

void wcs_handler(HRW_rcd *ptr){
   count--;
   fprintf(Sdf::trace, "node%d: global-writing's over on call side\n", Sdf::PROC_ID);
   Sdf::Access_type access_type;
   int tag_dv = ptr->get_tag_dv(&access_type);
   fprintf(Sdf::trace, "node%d: wcs_handler, rem_proc=%d, d_ptr=%d, g-sz=%d, th_ptr=%d, hndlr_ptr=%d, hndlr_d_ptr=%d, tag_dv=%d, atype=%d, tag_av=%d, tag_ev=%d, comm=%d, offset=%d, Tsize=%d\n",
           Sdf::PROC_ID, ptr->get_remote_proc(),
           ptr->get_data_ptr(), ptr->get_given_size(),
           ptr->get_thread_ptr(), ptr->get_hndlr_ptr(),
           ptr->get_hndlr_data_ptr(),
           tag_dv,
           access_type,
           ptr->get_tag_av(),
           ptr->get_tag_ev(),
           ptr->get_comm(),
           ptr->get_offset(),
           ptr->get_Tsize());
   fflush(Sdf::trace);
}

void wts_handler(void *){
   fprintf(Sdf::trace, "node%d: global-writing's over on target side\n", Sdf::PROC_ID);
   fflush(Sdf::trace);
}

void rcs_handler(HRW_rcd *ptr){
   count--;
   fprintf(Sdf::trace, "node%d: global-reading's over on call side\n", Sdf::PROC_ID);
   Sdf::Access_type access_type;
   int tag_dv = ptr->get_tag_dv(&access_type);
   fprintf(Sdf::trace, "node%d: rcs_handler, rem_proc=%d, d_ptr=%d, g-sz=%d, r_sz=%d, th_ptr=%d, hndlr_ptr=%d, hndlr_d_ptr=%d, tag_dv=%d, atype=%d, tag_av=%d, tag_ev=%d, comm=%d, offset=%d, Tsize=%d\n",
           Sdf::PROC_ID, 
           ptr->get_remote_proc(),
           ptr->get_data_ptr(), 
           ptr->get_given_size(),
           ptr->get_rcvd_size(), 
           ptr->get_thread_ptr(),
           ptr->get_hndlr_ptr(), 
           ptr->get_hndlr_data_ptr(),
           tag_dv,
           access_type,
           ptr->get_tag_av(),
           ptr->get_tag_ev(),
           ptr->get_comm(),
           ptr->get_offset(),
           ptr->get_Tsize());
   fflush(Sdf::trace);
}

void rts_handler(void *){
   fprintf(Sdf::trace, "node%d: global-reading's over on target side\n", Sdf::PROC_ID);
}

char* rwloc_fct(IDH_rcd *ptr){
   Sdf::Access_type access_type;
   int tag_dv = ptr->get_tag_dv(&access_type);
   int op_type = ptr->get_rarg(0);  //0:write, 1:read
   if(op_type)
      ptr->set_sent_size(14);
   fprintf(Sdf::trace, "node%d: loc_fct, src_proc=%d, sz=%d, sent-sz=%d, offset=%d, rarg0=%d, rarg1=%d, tag_dv=%d, atype=%d, tag_av=%d, tag_ev=%d, comm=%d, offset=%d, Tsize=%d\n",
           Sdf::PROC_ID,  
           ptr->get_remote_proc(),
           ptr->get_given_size(), 
           (op_type? ptr->get_sent_size() :  -1),
           ptr->get_offset(), 
           ptr->get_rarg(0),
           ptr->get_rarg(1),
           tag_dv,
           access_type,
           ptr->get_tag_av(),
           ptr->get_tag_ev(),
           ptr->get_comm(),
           ptr->get_offset(),
           ptr->get_Tsize());
   fflush(Sdf::trace);

   if(op_type)
      ptr->set_handler(rts_handler, 0);
   else
      ptr->set_handler(wts_handler, 0);
   return rw_target_adrs;
}

class Root_thread: public Thread{
   public:
        Root_thread()
                : Thread((Tmf0_ptr)&Root_thread::body){}

        void body(){

           fprintf(Sdf::trace, "from node%d: this is my rank\n", Sdf::PROC_ID);
           fflush(Sdf::trace);

           char source_data[21];
           char rw_target[21];
           char dest_data[21];
           rw_target_adrs = rw_target;

           int s;
           for(s=0; s<21; s++)
              source_data[s]  = Sdf::PROC_ID;
           for(s=0; s<21; s++)
              rw_target[s]    = 50+Sdf::PROC_ID;
           for(s=0; s<21; s++)
              dest_data[s]    = 100+Sdf::PROC_ID;

           int i;
           for(i=0; i<21; i++)
             fprintf(Sdf::trace, "node%d: s[%d]=%d, t[%d]=%d, d[%d]=%d\n",
                     Sdf::PROC_ID, i, source_data[i], i, rw_target[i], i, dest_data[i]);
           fflush(Sdf::trace);

           Global<char> global(gid, rwloc_fct);
           Sdf::barrier(cid1);
            //global synchonization of Global constructors has become useless
            //starting from version 5

           count = 0;
           int w_rarg[2] = {0, MXINT}; //first element identifies write op
                                       //second element does not matter
           global.write(Sdf::PROC_ID, 0, 
                        source_data[0], 21, wcs_handler, 0, w_rarg);
           count++;
           while(count)
              Sdf::poll();

           Sdf::barrier(cid2);

           count++;
           int r_rarg[2] = {1, MXINT}; //first element identifies read op
                                       //second element does not matter


           global.read(Sdf::PROC_ID, 0, 
                       dest_data[0], 21, rcs_handler, 0, r_rarg);

           while(count)
              Sdf::poll();

           Sdf::barrier(cid3);

           for(i=0; i<21; i++)
             fprintf(Sdf::trace, "node%d: s[%d]=%d, t[%d]=%d, d[%d]=%d\n",
                           Sdf::PROC_ID, i, source_data[i], i, rw_target[i], i, dest_data[i]);
           fflush(Sdf::trace);

           Sdf::barrier(cid4);

        }
};

MAIN(Root_thread, init_gid, Sdf::empty, Sdf::empty)
